<template>
  <app-view>
    <van-nav-bar left-text="人脸采集" left-arrow :border="false" @click-left="onClickLeft" />
    <van-form input-align="right" style="background: rgba(247, 247, 247, 1)" @submit="onSubmit">
      <van-field v-model="formData.name" readonly name="name" label="姓名" placeholder="" />
      <van-field v-model="formData.phone" readonly name="phone" label="手机号" placeholder="" />
      <!-- 改用下面的sdk图像接口 -->
      <van-field
        v-if="false"
        v-model="formData.faceUrl"
        class="icon-field required-item"
        readonly
        name="picker"
        label="照片"
        placeholder="选择照片"
        :rules="[{ required: true, message: '请选择照片' }]"
      >
        <!-- 有照片 -->
        <template v-if="oldFaceUrl" #input>
          <img
            :src="formData.faceUrl"
            alt=""
            class="uploader-icon"
            @click="previewImg(formData.faceUrl)"
          />
        </template>
        <!-- 没有照片 -->
        <template v-else #input>
          <van-uploader
            v-model="uploaderImg"
            :max-count="1"
            :max-size="15 * 1024 * 1024"
            :after-read="afterRead"
            @oversize="onOversize"
            @delete="onDelete"
          >
            <div class="uploader-icon uploader-icon-border">
              <van-icon class="van-icon" name="plus" />
            </div>
          </van-uploader>
        </template>
      </van-field>
      <van-field
        v-model="formData.faceUrl"
        class="icon-field required-item"
        readonly
        name="picker"
        label="照片"
        placeholder="选择照片"
        :rules="[{ required: true, message: '请选择照片' }]"
      >
        <wx-choose-image
          slot="input"
          class="uploader-icon"
          :count="1"
          :img="userAvatar"
          :show-loading="false"
          :disabled="!!userInfo.photo"
          @error-local="onErrorLocal"
          @change-local="onChangeLocal"
          @change-server="onChangeServer"
          @click.native="onImagePreview"
        />
      </van-field>
      <click-btn v-if="!oldFaceUrl" text="提交" native-type="submit" />
    </van-form>
    <click-btn v-if="oldFaceUrl" text="返回" @on-btn-click="onClickLeft()" />
  </app-view>
</template>

<script>
  import Exif from 'exif-js';
  import { mapGetters, mapActions } from 'vuex';
  import { ImagePreview } from 'vant';
  import WxChooseImage from '@components/wx-choose-image/index';
  import ClickBtn from '@views/modules/access/components/click-btn';
  import { isEmpty } from '@utils/util'; // 禁用物理返回键的方法
  import { wxFaceUpload } from '@api/mine';
  import { getUserInfo } from '@utils/auth';
  import { uploadFace } from '@api/common/user';

  export default {
    components: { ClickBtn, WxChooseImage },
    data() {
      return {
        loading: {},
        oldFaceUrl: getUserInfo() && getUserInfo().faceUrl, // 用户信息中的照片信息
        uploaderImg: [],
        files: {
          name: '',
          type: ''
        },
        formData: {
          placeUserId: getUserInfo() ? getUserInfo().placeUserId : null,
          faceUrl: getUserInfo() ? getUserInfo().faceUrl : null,
          name: getUserInfo() ? getUserInfo().userName : null,
          phone: getUserInfo() ? getUserInfo().phone : null
        } // 表单数据
      };
    },
    computed: {
      ...mapGetters('user', ['userInfo', 'userRoles']),
      userAvatar() {
        return this.formData.faceUrl || this.userInfo.photo || undefined;
      }
    },
    methods: {
      ...mapActions('user', ['updateUserInfo']),
      // -----------------图片处理的方法
      // 组件方法 获取 流
      afterRead(file) {
        this.files.name = file.file.name; // 获取文件名
        this.files.type = file.file.type; // 获取类型
        this.imgPreview(file.file);
      },
      // 处理图片
      imgPreview(file) {
        const self = this;
        let Orientation;
        // 去获取拍照时的信息，解决拍出来的照片旋转问题   npm install exif-js --save   这里需要安装一下包
        Exif.getData(file, function () {
          Orientation = Exif.getTag(this, 'Orientation');
        });
        // 看支持不支持FileReader
        if (!file || !window.FileReader) return;
        if (/^image/.test(file.type)) {
          // 创建一个reader
          const reader = new FileReader();
          // 将图片2将转成 base64 格式
          reader.readAsDataURL(file);
          // 读取成功后的回调
          reader.onloadend = function () {
            const result = this.result;
            const img = new Image();
            img.src = result;
            // 判断图片是否大于500K,是就直接上传，反之压缩图片
            if (this.result.length <= 500 * 1024) {
              // 上传图片
              self.postImg(this.result);
            } else {
              img.onload = function () {
                const data = self.compress(img, Orientation);
                // 上传图片
                self.postImg(data);
              };
            }
          };
        }
      },
      // 压缩图片
      compress(img, Orientation) {
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        // 瓦片canvas
        const tCanvas = document.createElement('canvas');
        const tctx = tCanvas.getContext('2d');
        // let initSize = img.src.length;
        let width = img.width;
        let height = img.height;
        // 如果图片大于四百万像素，计算压缩比并将大小压至400万以下
        let ratio;
        if ((ratio = (width * height) / 4000000) > 1) {
          // console.log("大于400万像素");
          ratio = Math.sqrt(ratio);
          width /= ratio;
          height /= ratio;
        } else {
          ratio = 1;
        }
        canvas.width = width;
        canvas.height = height;
        //    铺底色
        ctx.fillStyle = '#fff';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        // 如果图片像素大于100万则使用瓦片绘制
        let count;
        if ((count = (width * height) / 1000000) > 1) {
          // console.log("超过100W像素");
          count = ~~(Math.sqrt(count) + 1); // 计算要分成多少块瓦片
          //      计算每块瓦片的宽和高
          const nw = ~~(width / count);
          const nh = ~~(height / count);
          tCanvas.width = nw;
          tCanvas.height = nh;
          for (let i = 0; i < count; i++) {
            for (let j = 0; j < count; j++) {
              tctx.drawImage(
                img,
                i * nw * ratio,
                j * nh * ratio,
                nw * ratio,
                nh * ratio,
                0,
                0,
                nw,
                nh
              );
              ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
            }
          }
        } else {
          ctx.drawImage(img, 0, 0, width, height);
        }
        // 修复ios上传图片的时候 被旋转的问题
        if (Orientation !== '' && Orientation !== 1) {
          switch (Orientation) {
            case 6: // 需要顺时针（向左）90度旋转
              this.rotateImg(img, 'left', canvas);
              break;
            case 8: // 需要逆时针（向右）90度旋转
              this.rotateImg(img, 'right', canvas);
              break;
            case 3: // 需要180度旋转
              this.rotateImg(img, 'right', canvas); // 转两次
              this.rotateImg(img, 'right', canvas);
              break;
          }
        }
        // 进行最小压缩
        const ndata = canvas.toDataURL('image/jpeg', 0.1);
        tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
        // console.log(ndata);
        return ndata;
      },
      // 旋转图片
      rotateImg(img, direction, canvas) {
        // 最小与最大旋转方向，图片旋转4次后回到原方向
        const min_step = 0;
        const max_step = 3;
        if (img === null) return;
        // img的高度和宽度不能在img元素隐藏后获取，否则会出错
        const height = img.height;
        const width = img.width;
        let step = 2;
        if (step === null) {
          step = min_step;
        }
        if (direction === 'right') {
          step++;
          // 旋转到原位置，即超过最大值
          step > max_step && (step = min_step);
        } else {
          step--;
          step < min_step && (step = max_step);
        }
        // 旋转角度以弧度值为参数
        const degree = (step * 90 * Math.PI) / 180;
        const ctx = canvas.getContext('2d');
        switch (step) {
          case 0:
            canvas.width = width;
            canvas.height = height;
            ctx.drawImage(img, 0, 0);
            break;
          case 1:
            canvas.width = height;
            canvas.height = width;
            ctx.rotate(degree);
            ctx.drawImage(img, 0, -height);
            break;
          case 2:
            canvas.width = width;
            canvas.height = height;
            ctx.rotate(degree);
            ctx.drawImage(img, -width, -height);
            break;
          case 3:
            canvas.width = height;
            canvas.height = width;
            ctx.rotate(degree);
            ctx.drawImage(img, -width, 0);
            break;
        }
      },
      // 将base64转换为文件
      dataURLtoFile(dataurl) {
        var arr = dataurl.split(',');
        var bstr = atob(arr[1]);
        var n = bstr.length;
        var u8arr = new Uint8Array(n);
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n);
        }
        return new File([u8arr], this.files.name, {
          type: this.files.type
        });
      },
      // 提交图片到后端
      postImg(base64) {
        const file = this.dataURLtoFile(base64);
        const formData = new window.FormData();
        formData.append('file', file);
        this.faceUpload(formData);
        // 提交图片
        // Some code
      },
      // ----------------- 图片处理的方法-end
      // 删除照片点击
      onDelete() {
        this.formData.faceUrl = null;
      },
      // 选择照片后是上传
      // onAfterRead(fileInfo) {
      //   const formData = new FormData();
      //   formData.append('file', fileInfo.file);
      //   this.faceUpload(formData);
      // },
      // 图片大小限制超过提示
      onOversize(file) {
        this.$toast('文件大小不能超过15M');
      },
      // 预览图片
      previewImg(url) {
        url && ImagePreview([url]);
      },
      // 后退点击
      onClickLeft() {
        this.$router.push('../user');
      },
      onSubmit() {
        const _self = this;
        if (!_self.formData.faceUrl) {
          _self.uploaderImg = [];
          return _self.$toast('照片上传失败，请稍后再试');
        }
        this.$dialog
          .confirm({
            title: '提示',
            message: '照片提交后不可修改，确定要提交？'
          })
          .then(() => {
            _self.wxFaceUpdate();
          })
          .catch(() => {});
      },
      // 请求的方法
      faceUpload(file) {
        const _self = this;
        const loading = this.$toast.loading('正在上传，请稍候...');
        wxFaceUpload(file)
          .then((res) => {
            const { success, data, msg } = res;
            if (success) {
              _self.$toast({ duration: 1000, message: '照片上传成功' });
              _self.formData.faceUrl = data;
            } else {
              _self.$toast(msg);
              _self.formData.faceUrl = null;
            }
          })
          .finally(() => loading.clearLoading());
      },
      wxFaceUpdate() {
        const _self = this;
        const data = {
          placeUserId: getUserInfo().placeUserId,
          photo: _self.formData.faceUrl
        };
        const loading = this.$toast.loading('加载中...');
        this.updateUserInfo(data)
          .then((success, msg) => {
            if (!success) return this.$toast(msg);
            setTimeout(() => {
              _self.onClickLeft();
            }, 1000);
          })
          .finally(() => loading.clearLoading());
      },
      // SDK 选取本地图片错误
      onErrorLocal(error) {
        this.loading.clearLoading();
        this.$toast(error);
      },
      // SDK 选取本地图片
      onChangeLocal() {
        this.loading = this.$toast.loading('正在上传，请稍后...');
      },
      // SDK 图片上传完成返回服务器ID
      onChangeServer(serverIds) {
        uploadFace({ mediaId: serverIds[0] })
          .then(({ success, data }) => {
            this.$toast(success ? '照片上传成功' : '人脸不合格');

            this.formData.faceUrl = success ? data : '';
          })
          .finally(() => this.loading.clearLoading());
      },
      // 图片预览
      onImagePreview() {
        const { photo } = this.userInfo;

        if (isEmpty(photo)) return false;

        ImagePreview([photo]);
      }
    }
  };
</script>

<style scoped lang="less">
  @import '~@styles/var';
  @import '~@styles/modules/visitor/van-form';
  @import '~@styles/modules/visitor/van-popup';
  .app-view {
    background: #f7f7f7;
  }
  .uploader-icon {
    --size: 70px;

    width: var(--size);
    height: var(--size);
    line-height: calc(var(--size) + 10px);
    text-align: center;
    opacity: 0.76;

    .van-icon {
      font-size: 24px;
    }
  }
  .uploader-icon-border {
    border: 1px dashed rgba(147, 147, 147, 1);
  }
  .van-form {
    /deep/ .icon-field {
      height: 105px !important;
    }
    .icon-field /deep/ .van-field__error-message {
      top: 0 !important;
    }
  }
  .van-nav-bar {
    background-color: #fff;
  }
</style>
